package com.flyme.common.poi.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yanxin.li@ucarinc.com
 */
public class WordTemplateUtil {
    /**
     * 从模版中生成XWPFDocument
     *
     * @param templateFilePath
     * @param data
     * @return
     * @throws IOException
     */
    public static XWPFDocument generateWordFromTemplate(String templateFilePath, WordTemplateData data) throws IOException {
        if (data == null) {
            throw new RuntimeException("WordTemplateData can not be null");
        }

        if (data.getPlainTextData().isEmpty() && data.getTableData().isEmpty()) {
            throw new RuntimeException("the plain text data and table data can not be empty");
        }

        try {
            InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(templateFilePath);
            if (input == null) {
                throw new RuntimeException("error");
            }
            XWPFDocument document = new XWPFDocument(input);
            /* 在段落中查找并替换 */
            document = replaceTextInPlaintext(document, data.getPlainTextData());
            /* 在表格中查找并替换 */
            document = replaceTextInTable(document, data.getTableData());
            return document;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 替换普通文本中的变量字符串
     *
     * @param doc
     * @param plainTextData
     * @return
     */
    @SuppressWarnings("deprecation")
    private static XWPFDocument replaceTextInPlaintext(XWPFDocument doc, Map<String, String> plainTextData) {
        /* 遍历文档中所有普通文本段落 */
        List<XWPFParagraph> paras = doc.getParagraphs();
        for (XWPFParagraph para : paras) {
            CTR[] ctrs = para.getCTP().getRArray();
            for (CTR ctr : ctrs) {
                CTText[] texts = ctr.getTArray();
                for (CTText text : texts) {
                    String textData = text.getStringValue() == null ? "" : text.getStringValue();
                    textData = replaceText(plainTextData, textData);
                    text.setStringValue(textData);
                }
            }
        }
        return doc;
    }


    /**
     * 替换表格中的变量字符串
     *
     * @param doc
     * @param tableData
     * @return
     */
    private static XWPFDocument replaceTextInTable(XWPFDocument doc, Map<String, String> tableData) {
        List<XWPFTable> xwpfTables = doc.getTables();
        // 开始迭代表格
        for (int i = 0; i < xwpfTables.size(); i++) {
            // 迭代第一个表格
            XWPFTable xwpfTable = xwpfTables.get(i);
            // 得到表格的行数
            List<XWPFTableRow> rows = xwpfTable.getRows();
            for (int j = 0; j < rows.size(); j++) {
                // 迭代表格的行数
                XWPFTableRow tableRow = rows.get(j);
                List<XWPFTableCell> rowCells = tableRow.getTableCells();
                for (int k = 0; k < rowCells.size(); k++) {
                    XWPFTableCell tableCell = rowCells.get(k);
                    /* 遍历表格中所有段落，找到可替换字符串并替换 */
                    List<XWPFParagraph> paras = tableCell.getParagraphs();
                    for (XWPFParagraph para : paras) {
                        if (para.getRuns().size() == 0) {
                            continue;
                        }
                        List<XWPFRun> runs = para.getRuns();
                        StringBuilder runText = new StringBuilder();
                        for (XWPFRun run : runs) {
                            runText.append(StringUtils.trim(run.getText(0)));
                            run.setText(StringUtils.EMPTY, 0);
                        }

                        String runTextData = replaceText(tableData, runText.toString());
                        para.getRuns().get(0).setText(runTextData, 0);
                    }
                }
            }
        }
        return doc;
    }


    /**
     * 根据Map中的所有key寻找匹配字符串，如果找到则用对应的value替换
     *
     * @param data
     * @param placeHolder
     * @return 返回替换后的文本
     */
    private static String replaceText(Map<String, String> data, String placeHolder) {
        if (StringUtils.equals(placeHolder, "null")) {
            return StringUtils.EMPTY;
        }
        Matcher m = Pattern.compile("\\{([A-Za-z0-9]+)\\}").matcher(placeHolder);
        while (m.find()) {
            String key = StringUtils.substringBetween(m.group(), "{", "}");
            if (data.get(key) == null) {
                placeHolder = StringUtils.replace(placeHolder, m.group(), "____");
            }
            placeHolder = StringUtils.replace(placeHolder, m.group(), data.get(key));
        }
        return placeHolder;
    }

//    public static void main(String args[]) {
//        String text = "你好{placeHolder} 我们";
//        Matcher m = Pattern.compile("\\{([A-Za-z]+)\\}").matcher(text);
//        int count = 0;
//        while (m.find()) {
//            String key = StringUtils.substringBetween(m.group(), "{", "}");
//            System.out.println(key);
//            text = text.replace(m.group(), String.valueOf(count));
//        }
//        System.out.println(text);
//    }

}
